package facepp

import (
	"fmt"
	"time"

	"github.com/go-resty/resty/v2"
)

type FaceSearchFace struct {
	Face_rectangle struct {
		Left   int `json:"left"`
		Top    int `json:"top"`
		Width  int `json:"width"`
		Height int `json:"height"`
	} `json:"face_rectangle"`
	Face_token string `json:"face_token"`
}

type FaceSearchResult struct {
	Confidence float64 `json:"confidence"`
	UserId     string  `json:"user_id"`
	FaceToken  string  `json:"face_token"`
}

type FaceSearchResp struct {
	Image_id   string             `json:"image_id"`
	Faces      []FaceSearchFace   `json:"faces"`
	Time_used  int                `json:"time_used"`
	Request_id string             `json:"request_id"`
	Results    []FaceSearchResult `json:"results"`
}

// 人脸搜索，根据图片地址搜索
func (f *FacePP) FaceSearchByImageUrl(imageUrl string, facesetToken, outerId string, returnResultCount string) (*FaceSearchResp, error) {
	if imageUrl == "" {
		return nil, fmt.Errorf(CallApiErrFormat2, ParamsInvalid.Code, fmt.Sprintf(ParamsInvalid.Message, "imageUrl"))
	}
	if facesetToken == "" && outerId == "" {
		return nil, fmt.Errorf(CallApiErrFormat2, ParamsInvalid.Code, fmt.Sprintf(ParamsInvalid.Message, "facesetToken or outerId"))
	}
	params := make(map[string]string)
	params["api_key"] = f.ApiKey
	params["api_secret"] = f.ApiSecret
	params["image_url"] = imageUrl
	if facesetToken != "" {
		params["faceset_token"] = facesetToken
	}
	if outerId != "" {
		params["outer_id"] = outerId
	}
	if returnResultCount != "" {
		params["return_result_count"] = returnResultCount
	}

	var faceSearchResp FaceSearchResp
	var apiErrResp ApiErrResp
	client := resty.New()
	client.SetTimeout(10 * time.Second)
	resp, err := client.R().
		SetHeader(ACCEPT, APP_JSON).
		SetFormData(params).
		SetResult(&faceSearchResp).
		SetError(&apiErrResp).
		Post(FACE_SEARCH_URL)
	if err != nil {
		return nil, fmt.Errorf(CallApiErrFormat2, HttpClientReqError.Code, HttpClientReqError.Message)
	}
	if resp.StatusCode() != 200 {
		return nil, fmt.Errorf(CallApiErrFormat2, resp.StatusCode(), apiErrResp.Error_message)
	}
	return &faceSearchResp, nil
}

// 人脸搜索，根据图片文件搜索
func (f *FacePP) FaceSearchByImageFile(filepath string, facesetToken, outerId string, returnResultCount string) (*FaceSearchResp, error) {
	if filepath == "" {
		return nil, fmt.Errorf(CallApiErrFormat2, ParamsInvalid.Code, fmt.Sprintf(ParamsInvalid.Message, "filepath"))
	}
	if facesetToken == "" && outerId == "" {
		return nil, fmt.Errorf(CallApiErrFormat2, ParamsInvalid.Code, fmt.Sprintf(ParamsInvalid.Message, "facesetToken or outerId"))
	}
	params := make(map[string]string)
	params["api_key"] = f.ApiKey
	params["api_secret"] = f.ApiSecret
	if facesetToken != "" {
		params["faceset_token"] = facesetToken
	}
	if outerId != "" {
		params["outer_id"] = outerId
	}
	if returnResultCount != "" {
		params["return_result_count"] = returnResultCount
	}

	var faceSearchResp FaceSearchResp
	var apiErrResp ApiErrResp
	client := resty.New()
	client.SetTimeout(10 * time.Second)
	resp, err := client.R().
		SetHeader(ACCEPT, APP_JSON).
		SetFile("image_file", filepath).
		SetFormData(params).
		SetResult(&faceSearchResp).
		SetError(&apiErrResp).
		Post(FACE_SEARCH_URL)
	if err != nil {
		return nil, fmt.Errorf(CallApiErrFormat2, HttpClientReqError.Code, HttpClientReqError.Message)
	}
	if resp.StatusCode() != 200 {
		return nil, fmt.Errorf(CallApiErrFormat2, resp.StatusCode(), apiErrResp.Error_message)
	}
	return &faceSearchResp, nil
}

// 人脸搜索，根据图片base64搜索。
// 注意：imageBase64的编码格式为UTF-8
func (f *FacePP) FaceSearchByImageBase64(imageBase64 string, facesetToken, outerId string, returnResultCount string) (*FaceSearchResp, error) {
	if imageBase64 == "" {
		return nil, fmt.Errorf(CallApiErrFormat2, ParamsInvalid.Code, fmt.Sprintf(ParamsInvalid.Message, "imageBase64"))
	}
	if facesetToken == "" && outerId == "" {
		return nil, fmt.Errorf(CallApiErrFormat2, ParamsInvalid.Code, fmt.Sprintf(ParamsInvalid.Message, "facesetToken or outerId"))
	}
	params := make(map[string]string)
	params["api_key"] = f.ApiKey
	params["api_secret"] = f.ApiSecret
	params["image_base64"] = imageBase64
	if facesetToken != "" {
		params["faceset_token"] = facesetToken
	}
	if outerId != "" {
		params["outer_id"] = outerId
	}
	if returnResultCount != "" {
		params["return_result_count"] = returnResultCount
	}

	var faceSearchResp FaceSearchResp
	var apiErrResp ApiErrResp
	client := resty.New()
	client.SetTimeout(10 * time.Second)
	resp, err := client.R().
		SetHeader(ACCEPT, APP_JSON).
		SetFormData(params).
		SetResult(&faceSearchResp).
		SetError(&apiErrResp).
		Post(FACE_SEARCH_URL)
	if err != nil {
		return nil, fmt.Errorf(CallApiErrFormat2, HttpClientReqError.Code, HttpClientReqError.Message)
	}
	if resp.StatusCode() != 200 {
		return nil, fmt.Errorf(CallApiErrFormat2, resp.StatusCode(), apiErrResp.Error_message)
	}
	return &faceSearchResp, nil
}

// 人脸搜索，根据face_token搜索
func (f *FacePP) FaceSearchByFaceToken(faceToken string, facesetToken, outerId string, returnResultCount string) (*FaceSearchResp, error) {
	if faceToken == "" {
		return nil, fmt.Errorf(CallApiErrFormat2, ParamsInvalid.Code, fmt.Sprintf(ParamsInvalid.Message, "faceToken"))
	}
	if facesetToken == "" && outerId == "" {
		return nil, fmt.Errorf(CallApiErrFormat2, ParamsInvalid.Code, fmt.Sprintf(ParamsInvalid.Message, "facesetToken or outerId"))
	}
	params := make(map[string]string)
	params["api_key"] = f.ApiKey
	params["api_secret"] = f.ApiSecret
	params["face_token"] = faceToken
	if facesetToken != "" {
		params["faceset_token"] = facesetToken
	}
	if outerId != "" {
		params["outer_id"] = outerId
	}
	if returnResultCount != "" {
		params["return_result_count"] = returnResultCount
	}

	var faceSearchResp FaceSearchResp
	var apiErrResp ApiErrResp
	client := resty.New()
	client.SetTimeout(10 * time.Second)
	resp, err := client.R().
		SetHeader(ACCEPT, APP_JSON).
		SetFormData(params).
		SetResult(&faceSearchResp).
		SetError(&apiErrResp).
		Post(FACE_SEARCH_URL)
	if err != nil {
		return nil, fmt.Errorf(CallApiErrFormat2, HttpClientReqError.Code, HttpClientReqError.Message)
	}
	if resp.StatusCode() != 200 {
		return nil, fmt.Errorf(CallApiErrFormat2, resp.StatusCode(), apiErrResp.Error_message)
	}
	return &faceSearchResp, nil
}
